package org.opentcs.kcvehicle.communication.kc.udp.agv.codec;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.socket.DatagramPacket;
import java.net.InetSocketAddress;
import org.opentcs.kcvehicle.communication.kc.common.Package;
import org.opentcs.kcvehicle.communication.kc.service.KCCommunicationImpl;
import org.opentcs.kcvehicle.communication.kc.syn.SendedList;
import org.opentcs.kcvehicle.communication.kc.udp.agv.param.rsp.RcvEventPackage;


public class KCAgvUdpDecode
    extends
      SimpleChannelInboundHandler<DatagramPacket> {

  private KCCommunicationImpl client;

  //授权码16字节 + 报文头8个字节 + 报文数据长度2个字节 + 保留2字节 = 28字节
  private static final int HEADER_SIZE = 28;

  public KCAgvUdpDecode(KCCommunicationImpl client) {
    this.client = client;
  }

  @Override
  protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg)
      throws Exception {
    //获得应答，DatagramPacket提供了content()方法取得报文的实际内容
    ByteBuf in = msg.content();
    if (in.readableBytes() < HEADER_SIZE) {
      throw new Exception("readed bytes < header length");
    }

    int dataLength = in.getShortLE(24);
    if (dataLength < 0) {
      throw new Exception(
          "bodyLength [" + dataLength + "] is not right, remote:" + ctx.channel().remoteAddress()
      );
    }

    int neededLength = HEADER_SIZE + dataLength;
    int isDataEnough = in.readableBytes() - neededLength;


    //收到的数据是否足够组包
    if (isDataEnough < 0) {
      // 不够消息体长度(剩下的buffe组不了消息体),重新去组包
      throw new Exception("readed bytes < content length");
    }
    else {

      //todo这里重写subscribe 的逻辑,注意要区分是 订阅的还是 主动请求的。
      //组包成功
      byte[] body = new byte[neededLength];
      in.readBytes(body);
      //System.out.println("received bytes :"+ Arrays.toString(body));
      String uuid = body[18] + "-" + body[19];
      Package mbPackage = new Package(body, uuid);
      byte commandCode = body[21];

      if (body[18] == (byte) 0x00 && body[19] == (byte) 0x00) {
        //获取响应IP
        InetSocketAddress sender = msg.sender();
        String hostAddress = sender.getAddress().getHostAddress();

        if (commandCode == (byte) 0xAF || commandCode == (byte) 0xB0) {
          client.subscribeKC(new RcvEventPackage(body[22], body), body);
        }
        else {
          SendedList.set(uuid, mbPackage);
        }
      }
      else {
        SendedList.set(uuid, mbPackage);
      }
    }
  }

  @Override
  public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
      throws Exception {
    cause.printStackTrace();
    ctx.close();
  }
}
